package com.chenyue.cm.api.match;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.chenyue.cm.auth.Login;
import com.chenyue.cm.auth.LoginUser;
import com.chenyue.cm.auth.token.LoginUserInfo;
import com.chenyue.cm.auth.token.RequestUtil;
import com.chenyue.cm.bean.Success;
import com.chenyue.cm.common.constant.ConstantValues;
import com.chenyue.cm.common.domain.JdSearchHistory;
import com.chenyue.cm.common.service.CommonInfoService;
import com.chenyue.cm.common.service.JdSearchHistoryService;
import com.chenyue.cm.common.utils.StringUtils;
import com.chenyue.cm.common.vo.Page;
import com.chenyue.cm.match.domain.*;
import com.chenyue.cm.match.service.*;
import com.chenyue.cm.match.vo.Address;
import com.chenyue.cm.match.vo.DataCenter;
import com.chenyue.cm.match.vo.GroupSignIn;
import com.chenyue.cm.match.vo.TemporaryTeam;
import com.chenyue.cm.order.domain.JdOrder;
import com.chenyue.cm.order.domain.JdProduct;
import com.chenyue.cm.payment.service.JdOrderService;
import com.chenyue.cm.user.domain.JdAppUser;
import com.chenyue.cm.user.service.JdAppUserService;
import com.chenyue.cm.user.vo.CheckMobileUserVo;
import com.chenyue.cm.utils.DateUtils;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSort;
import io.swagger.annotations.*;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * @Author: ljy
 * @Title: ApiMatchController
 * @Description: 赛事Api
 * @Date: 2021-07-26
 */
@RestController
@RequestMapping("/api/match")
@Api(value = "赛事api", tags = "赛事api")
@ApiSort(4)
public class ApiMatchController {

    private final JdMatchService jdMatchService;

    private final JdSearchHistoryService jdSearchHistoryService;

    private final JdMatchScoreRecordService jdMatchScoreRecordService;

    private final JdMatchGroupService jdMatchGroupService;

    private final JdMatchTypeService jdMatchTypeService;

    private final JdMatchItemService matchItemService;

    private final JdAppUserService jdAppUserService;

    private final JdOrderService orderService;

    private final JdMatchSignService matchSignService;

    private final JdMatchAppointmentService matchAppointmentService;

    private final CommonInfoService commonInfoService;

    public ApiMatchController(
            JdMatchService jdMatchService,
            JdSearchHistoryService jdSearchHistoryService, JdMatchScoreRecordService jdMatchScoreRecordService,
            JdMatchGroupService jdMatchGroupService,
            JdMatchTypeService jdMatchTypeService,
            JdMatchItemService matchItemService,
            JdAppUserService jdAppUserService,
            JdOrderService orderService, JdMatchSignService matchSignService, JdMatchAppointmentService matchAppointmentService, CommonInfoService commonInfoService) {
        this.jdMatchService = jdMatchService;
        this.jdSearchHistoryService = jdSearchHistoryService;
        this.jdMatchScoreRecordService = jdMatchScoreRecordService;
        this.jdMatchGroupService = jdMatchGroupService;
        this.jdMatchTypeService = jdMatchTypeService;
        this.matchItemService = matchItemService;
        this.jdAppUserService = jdAppUserService;
        this.orderService = orderService;
        this.matchSignService = matchSignService;
        this.matchAppointmentService = matchAppointmentService;
        this.commonInfoService = commonInfoService;
    }

    /**
     * 赛事列表，可根据参赛范围，参赛类型筛选
     *
     * @return Success
     */
    @PostMapping("/getMatchList")
    @ApiOperation(value = "全部赛事列表", notes = "全部赛事列表")
    @ApiOperationSupport(order = 1)
    @ApiImplicitParams({
            @ApiImplicitParam(value = "当前页", name = "page", dataType = "int", required = true),
            @ApiImplicitParam(value = "条数", name = "rows", dataType = "int", required = true),
            @ApiImplicitParam(value = "赛事分类（分类表id）", name = "type", dataType = "int", required = true),
            @ApiImplicitParam(value = "参赛范围（1单人/2团体）", name = "matchGroup", dataType = "int", required = true),
            @ApiImplicitParam(value = "参赛类型（1单人单项/2单人多项/3多人多项）", name = "matchType", dataType = "int", required = true),
            @ApiImplicitParam(value = "当前城市Code", name = "city", dataType = "int", required = true),
            @ApiImplicitParam(value = "搜索关键词", name = "keyWords", dataType = "string"),
    })
    public Success<Page<List<MatchInfo>>> getAllMatch(
            @RequestParam(defaultValue = "1") Integer page,
            @RequestParam(defaultValue = "10") Integer rows,
            Integer type,
            Integer matchGroup,
            Integer matchType, String keyWords, Integer city,
            HttpServletRequest request
    ) {
        Address address = new Address();
        if (city != null) {
            address = commonInfoService.getAddressByArea(city);
        }
        Page<List<MatchInfo>> allMatch = jdMatchService.getAllMatch(page, rows, type, matchGroup, matchType, keyWords, address.getCity(), address.getProvince());
        if (StringUtils.isNotBlank(keyWords)) {
            JdSearchHistory history = new JdSearchHistory();
            history.setType(3);
            history.setContent(keyWords);
            history.setCt(Calendar.getInstance().getTime());
            int userId = 0;
            try {
                final LoginUserInfo userInfo = RequestUtil.getUserInfoByRequest(request);
                userId = userInfo.getUserId();
            } catch (Exception e) {
                e.printStackTrace();
            }
            history.setUserId(userId);
            jdSearchHistoryService.save(history);
        }
        return Success.success(allMatch);
    }

    /**
     * @return Success
     */
    @PostMapping("/matchInfo")
    @ApiOperation(value = "单个赛事详情", notes = "单个赛事详情")
    @ApiOperationSupport(order = 2)
    @ApiImplicitParams({
            @ApiImplicitParam(value = "赛事id", name = "matchId", dataType = "int", required = true),
            @ApiImplicitParam(value = "直播记录id", name = "recordId", dataType = "int", required = true),
    })
    public Success<MatchInfo> matchInfo(
            Integer matchId, Integer recordId,
            HttpServletRequest request
    ) {
        int userId = 0;
        try {
            final LoginUserInfo userInfo = RequestUtil.getUserInfoByRequest(request);
            userId = userInfo.getUserId();
        } catch (Exception e) {
            e.printStackTrace();
        }
        JdMatch match = jdMatchService.getById(matchId);
        MatchInfo matchInfo = jdMatchService.matchInfo(matchId, null);
        if (1 == match.getState()) {
            matchInfo.setGroupUserList(jdMatchGroupService.groupUsers(matchId));
            matchInfo.setUserList(jdMatchGroupService.userList(matchId));
        } else if (2 == match.getState()) {
            matchInfo.setRemark(match.getRemark());
        }
        if (userId > 0) {
            final JdMatchSign one = matchSignService.lambdaQuery().eq(JdMatchSign::getUserId, userId).eq(JdMatchSign::getMatchId, match.getId()).one();
            if (one != null) {
                matchInfo.setIsSign(1);
            }
            if (recordId != null && recordId > 0) {
                final JdMatchAppointment appointment = matchAppointmentService.lambdaQuery()
                        .eq(JdMatchAppointment::getLiveRecordId, recordId)
                        .eq(JdMatchAppointment::getUserId, userId).one();
                matchInfo.setHasAppointment(appointment == null ? 2 : 1);
            }
        }
        matchInfo.setPayContent(commonInfoService.constantValues(ConstantValues.PAY_CONTENT));
        return Success.success(matchInfo);
    }

    /**
     * 用户报名校验（0普通人 1队员 2队长）
     *
     * @return Success
     */
    @Login
    @PostMapping("/checkUserSign")
    @ApiOperation(value = "用户报名校验（0普通人 1队长 2队员）", notes = "用户报名校验（0普通人 1队长 2队员）")
    @ApiOperationSupport(order = 3)
    @ApiImplicitParams({
            @ApiImplicitParam(value = "赛事id", name = "matchId", dataType = "int", required = true),
    })
    public Success<String> checkUserSign(Integer matchId, @ApiIgnore @LoginUser JdAppUser user) {
        String msg = jdMatchService.checkUserSign(Integer.valueOf(user.getId()), matchId);
        return Success.success(msg);
    }

    /**
     * @return Success
     */
    @Login
    @PostMapping("/personSign")
    @ApiOperation(value = "赛事个人报名", notes = "赛事个人报名")
    @ApiOperationSupport(order = 4)
    @ApiImplicitParams({
            @ApiImplicitParam(value = "赛事id", name = "matchId", dataType = "int", required = true),
            @ApiImplicitParam(value = "姓名", name = "userName", dataType = "string", required = true),
            @ApiImplicitParam(value = "手机号", name = "mobile", dataType = "string", required = true),
            @ApiImplicitParam(value = "价格", name = "signAmount", dataType = "string", required = true)
    })
    @Transactional(rollbackFor = Exception.class)
    public Success<JdOrder> personSign(
            Integer matchId, String mobile, Double signAmount,
            @ApiIgnore @LoginUser JdAppUser appUser, Address address
    ) {
        final JdMatch one = jdMatchService.lambdaQuery().eq(JdMatch::getId, matchId).one();
        if (one.getEndTime().before(Calendar.getInstance().getTime())) {
            return Success.error("报名已结束");
        }
//        报名地点校验
        address = commonInfoService.getAddressByArea(Integer.parseInt(address.getArea()));
        String msg = jdMatchService.checkAddress(matchId, address);
        if (StringUtils.isNotBlank(msg)) {
            return Success.error(msg);
        }
        //校验这个手机号是否注册过 为回显值，无需校验
        //是否已经报过名
        String checkMsg = jdMatchService.checkUserCreate(Integer.valueOf(appUser.getId()), matchId);
        if (StringUtils.isNotBlank(checkMsg)) {
            return Success.error(checkMsg);
        }
        //报名是否需要审核
        final JdMatch match = jdMatchService.getById(matchId);
        JdOrder order = null;
        if (match.getPayType() != 0) {
            order = getJdOrder(matchId, signAmount, appUser);
        }
        if (match.getIsPublic() == 1) {
            //个人报名
            jdMatchService.personSign(mobile, matchId, 1, match.getPayType());
        } else {
            jdMatchService.personSign(mobile, matchId, 0, match.getPayType());
        }
        return Success.success(order);
    }

    private JdOrder getJdOrder(Integer matchId, Double signAmount, JdAppUser appUser) {
        final JdOrder one = orderService.lambdaQuery()
                .eq(JdOrder::getProductId, matchId)
                .eq(JdOrder::getUserId, appUser.getId()).one();
        if (one != null) {
            return one;
        }
        //创建报名订单
        JdProduct matchProduct = new JdProduct();
        //捷登体育-赛事报名 商品
        matchProduct.setType(3);
        matchProduct.setId(matchId);
        matchProduct.setSalePrice(signAmount);

        return orderService.createOrder(matchProduct, 1, Integer.valueOf(appUser.getId()));
    }

    @Login
    @PostMapping("/checkSignTime")
    @ApiOperation("报名检测（未开始/已结束）")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "赛事id", name = "matchId", dataType = "int", required = true),
    })
    public Success<String> checkSignTime(
            Integer matchId
    ) {
        final JdMatch match = jdMatchService.getById(matchId);
        if (match == null) {
            return Success.error();
        }
        final Date now = DateUtils.getToday();
        if (now.before(match.getStartTime())) {
            return Success.error("报名尚未开始");
        }
        if (now.after(match.getEndTime())) {
            return Success.error("报名已结束");
        }
        return Success.success();
    }

    /**
     * 团队报名 添加队员时校验
     *
     * @return Success
     */
    @Login
    @PostMapping("/checkTeamSignUser")
    @ApiOperation(value = "团队报名 添加每个队员时校验", notes = "团队报名 添加每个队员时校验")
    @ApiOperationSupport(order = 5)
    @ApiImplicitParams({
            @ApiImplicitParam(value = "赛事id", name = "matchId", dataType = "int", required = true),
            @ApiImplicitParam(value = "队员手机号", name = "mobile", dataType = "int", required = true),
    })
    public Success<String> checkTeamSignUser(Integer matchId, String mobile) {
        JdAppUser appUser = jdAppUserService.getJdAppUser(mobile);
        if (appUser != null) {
            String msg = jdMatchService.checkUserSign(Integer.valueOf(appUser.getId()), matchId);
            if (StringUtils.isNotBlank(msg)) {
                return Success.error(mobile + msg);
            }
        }
        return Success.success();
    }

    /**
     * 团队报名 添加队员时校验
     *
     * @return Success
     */
    @Login
    @PostMapping("/deleteTeamSignUser")
    @ApiOperation("团队报名 删除队员")
    @ApiOperationSupport(order = 5)
    @ApiImplicitParams({
            @ApiImplicitParam(value = "队伍id", name = "teamId", dataType = "int", required = true),
            @ApiImplicitParam(value = "队员用户id", name = "userId", dataType = "int", required = true),
    })
    public Success<String> deleteTeamSignUser(
            Integer teamId, Integer userId
    ) {
        jdMatchService.deleteTeamSignUser(teamId, userId);
        return Success.success();
    }

    @Login
    @PostMapping("/checkAddress")
    @ApiOperation("地区检验")
    public Success<String> checkAddress(
            @ApiParam @RequestBody Address address
    ) {
        final Integer matchId = address.getMatchId();
        address = commonInfoService.getAddressByArea(Integer.parseInt(address.getArea()));
        final String msg = jdMatchService.checkAddress(matchId, address);
        if (StringUtils.isNotBlank(msg)) {
            return Success.error(msg);
        }
        return Success.success();
    }

    /**
     * @return Success
     */
    @Login
    @PostMapping("/teamSign")
    @ApiOperation(value = "赛事团队报名(groupSignIn为实体类)", notes = "赛事团队报名(groupSignIn为实体类)")
    @ApiOperationSupport(order = 6)
    @Transactional(rollbackFor = Exception.class)
    public Success<JdOrder> teamSign(
            @ApiParam @RequestBody GroupSignIn groupSignIn,
            @ApiIgnore @LoginUser JdAppUser appUser
    ) {
        // 校验队员手机号是否注册过
        List<CheckMobileUserVo> mobileList = new ArrayList<>();
        for (GroupSignIn.TeamUser teamUser : groupSignIn.getTeamUserList()) {
            if (groupSignIn.getMobile().equals(teamUser.getMobile())) {
//                队长不会傻到录自己吧~
                return Success.error("队长已报名，请勿重复添加到队员中");
            }
            CheckMobileUserVo vo = new CheckMobileUserVo();
            vo.setUserName(teamUser.getName());
            vo.setMobile(teamUser.getMobile());
            mobileList.add(vo);
        }
//        报名地区校验
        groupSignIn.setAddress(commonInfoService.getAddressByArea(Integer.parseInt(groupSignIn.getAddress().getArea())));
        String msg = jdMatchService.checkAddress(groupSignIn.getMatchId(), groupSignIn.getAddress());
        if (StringUtils.isNotBlank(msg)) {
            return Success.error(msg);
        }
        jdAppUserService.checkMobileUser(mobileList);
        //校验团队人数
        final JdMatch match = jdMatchService.getById(groupSignIn.getMatchId());
        if (match.getSignCount() != groupSignIn.getTeamUserList().size() + 1) {
            return Success.error("填写人数与赛事要求团队人数不符");
        }
        JdOrder order = null;
//        是否免费
        if (match.getPayType() != 0) {
            order = getJdOrder(groupSignIn.getMatchId(), groupSignIn.getSignAmount(), appUser);
        }
        //报名是否需要审核
        if (match.getIsPublic() == 1) {
            //团队报名
            jdMatchService.teamSign(groupSignIn, groupSignIn.getMatchId(), 1, match.getPayType());
        } else {
            jdMatchService.teamSign(groupSignIn, groupSignIn.getMatchId(), 0, match.getPayType());
        }
        return Success.success(order);
    }

    /**
     * 临时组队列表
     *
     * @return Success
     */
    @PostMapping("/temporaryTeam")
    @ApiOperation(value = "赛事临时组队列表", notes = "赛事临时组队列表")
    @ApiOperationSupport(order = 7)
    @ApiImplicitParams({
            @ApiImplicitParam(value = "当前页", name = "page", dataType = "int", required = true),
            @ApiImplicitParam(value = "条数", name = "rows", dataType = "int", required = true),
            @ApiImplicitParam(value = "赛事id", name = "matchId", dataType = "int", required = true),
    })
    public Success<Page<List<TemporaryTeam>>> temporaryTeam(
            @RequestParam(defaultValue = "1") Integer page,
            @RequestParam(defaultValue = "10") Integer rows, Integer matchId) {
        Page<List<TemporaryTeam>> temporaryTeams = jdMatchService.temporaryTeam(page, rows, matchId);
        return Success.success(temporaryTeams);
    }

    /**
     * 查询单个用户发布的临时组队列表
     *
     * @return Success
     */
    @Login
    @PostMapping("/temporaryTeamByUser")
    @ApiOperation(value = "当前赛事用户发布的临时组队", notes = "当前赛事用户发布的临时组队")
    @ApiOperationSupport(order = 8)
    @ApiImplicitParams({
            @ApiImplicitParam(value = "赛事id", name = "matchId", dataType = "int", required = true),
    })
    public Success<TemporaryTeam> temporaryTeamByUser(Integer matchId, @ApiIgnore @LoginUser JdAppUser user) {
        TemporaryTeam team = jdMatchService.temporaryTeamByUser(matchId, Integer.valueOf(user.getId()));
        return Success.success(team);
    }

    /**
     * 检验用户能否发布临时组队
     *
     * @return Success
     */
    @Login
    @PostMapping("/checkUserCreate")
    @ApiOperation(value = "用户点击发布临时组队的校验", notes = "用户点击发布临时组队的校验")
    @ApiOperationSupport(order = 9)
    @ApiImplicitParams({
            @ApiImplicitParam(value = "赛事id", name = "matchId", dataType = "int", required = true),
    })
    public Success<String> checkUserCreate(Integer matchId, @ApiIgnore @LoginUser JdAppUser user) {
        String msg = jdMatchService.checkUserCreate(Integer.valueOf(user.getId()), matchId);
        if (StringUtils.isNotEmpty(msg)) {
            return Success.error(msg);
        }
        return Success.success();
    }

    /**
     * 用户发起临时组队
     *
     * @return Success
     */
    @PostMapping("/createTeam")
    @ApiOperation(value = "用户发布临时组队", notes = "用户发布临时组队")
    @ApiOperationSupport(order = 10)
    public Success<String> createTeam(@ApiParam @RequestBody JdMatchGroup matchGroup) {
        String msg = jdMatchService.checkUserCreate(matchGroup.getLeader(), matchGroup.getMatchId());
        if (StringUtils.isNotEmpty(msg)) {
            return Success.error(msg);
        } else {
            jdMatchService.createTeam(matchGroup);
            return Success.success("成功发起临时组队", "");
        }
    }

    /**
     * 用户参加临时组队
     *
     * @return Success
     */
    @Login
    @PostMapping("/joinTeam")
    @ApiOperation(value = "用户加入临时组队", notes = "用户加入临时组队")
    @ApiOperationSupport(order = 11)
    @ApiImplicitParams({
            @ApiImplicitParam(value = "队伍id", name = "teamId", dataType = "int", required = true),
            @ApiImplicitParam(value = "赛事id", name = "matchId", dataType = "int", required = true),
    })
    public Success<String> joinTeam(Integer teamId, Integer matchId, @ApiIgnore @LoginUser JdAppUser user) {
        return jdMatchService.joinTeam(Integer.valueOf(user.getId()), teamId, matchId);
    }

    /**
     * 单个赛事的数据中心
     *
     * @return Success
     */
    @PostMapping("/dataCenterByMatch")
    @ApiOperation(value = "数据中心", notes = "单个赛事的数据中心")
    @ApiOperationSupport(order = 12)
    @ApiImplicitParams({
            @ApiImplicitParam(value = "机构id/赛事发布人", name = "userId", dataType = "int"),
            @ApiImplicitParam(value = "赛事分类", name = "type", dataType = "int", required = true),
            @ApiImplicitParam(value = "赛事项目", name = "item", dataType = "int", required = true),
            @ApiImplicitParam(value = "赛事", name = "matchType", dataType = "int", required = true),
            @ApiImplicitParam(value = "参赛范围（1单人/2团体）", name = "matchGroup", dataType = "int", required = true),
            @ApiImplicitParam(value = "赛程阶段 1初2复3决", name = "arrangeOrder", dataType = "int", required = true),
            @ApiImplicitParam(value = "省", name = "province", dataType = "int", required = true),
            @ApiImplicitParam(value = "市", name = "city", dataType = "int", required = true),
            @ApiImplicitParam(value = "筛选赛事", name = "matchId", dataType = "Integer",required = true),
            @ApiImplicitParam(value = "时间（yyyy-MM-dd）", name = "date", dataType = "String", required = true),
    })
    public Success<Page<List<DataCenter>>> dataCenter(
            Integer type, Integer item, Integer matchType, Integer matchGroup, Integer arrangeOrder, Integer province, Integer city, String date, Integer matchId,
            @RequestParam(defaultValue = "1") Integer page,
            @RequestParam(defaultValue = "10") Integer rows,
            Integer userId
    ) {
        date += " 23:59:59";
        Integer count = jdMatchScoreRecordService.dataCenterCount(type, item, userId, matchType, matchGroup, arrangeOrder, province, city, date, matchId);
        final Page<List<DataCenter>> dataCenterPage = new Page<>(page, rows, count);
        List<DataCenter> list = jdMatchScoreRecordService.dataCenter(type, item, userId, matchType, matchGroup, arrangeOrder, province, city, date, matchId,dataCenterPage.convertPage());
        dataCenterPage.setContent(list);
        return Success.success(dataCenterPage);
    }

    @GetMapping("/getMatchType")
    @ApiOperation(value = "赛事分类", notes = "赛事分类")
    @ApiOperationSupport(order = 13)
    public Success<List<JdMatchType>> getMatchType() {
        List<JdMatchType> matchType = jdMatchTypeService.getMatchType();
        for (JdMatchType type : matchType) {
            final List<JdMatchItem> list = matchItemService.lambdaQuery().eq(JdMatchItem::getTypeId, type.getId()).list();
            type.setItemList(list);
        }
        return Success.success(matchType);
    }

    @GetMapping("/matchItemsByType")
    @ApiOperation(value = "赛事分类下的项目列表", notes = "赛事分类下的项目列表")
    @ApiOperationSupport(order = 14)
    public Success<List<JdMatchItem>> matchItemsByType(Integer typeId) {
        List<JdMatchItem> matchItemList = matchItemService.matchItemListByTypeId(typeId);
        return Success.success(matchItemList);
    }


    @GetMapping("/matchByName")
    @ApiOperation(value = "赛事筛选下的赛事名", notes = "赛事筛选下的赛事名")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "机构id/赛事发布人", name = "matchName", dataType = "int"),
            @ApiImplicitParam(value = "当前页", name = "page", dataType = "int", required = true),
            @ApiImplicitParam(value = "条数", name = "rows", dataType = "int", required = true),
    })
    @ApiOperationSupport(order = 15)
    public Success<Page<List<JdMatch>>> matchByName(String matchName,int page, int rows){
        LambdaQueryWrapper<JdMatch> wrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotEmpty(matchName)){
            wrapper.like(JdMatch::getName,matchName);
        }
        wrapper.eq(JdMatch::getState,1);
        final int total = jdMatchService.count(wrapper);
        final Page<List<JdMatch>> result = new Page<>(page, rows, total);
        wrapper.last(result.convertPage());
        wrapper.orderByDesc(JdMatch::getCt);
        List<JdMatch> list = jdMatchService.list(wrapper);
        result.setContent(list);
        return Success.success(result);
    }

}
